home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Night Owl 9
/
Night Owl CD-ROM (NOPV9) (Night Owl Publisher) (1993).ISO
/
015a
/
when33.zip
/
WHEN.ASM
next >
Wrap
Assembly Source File
|
1993-04-04
|
33KB
|
803 lines
PAGE 58,132
; WHEN - A Terminate & Stay Resident delayed activation utility
;
; ******************************************************************
; L E G A L B I T S
;
; WHEN, and all the ancillary programs in this package are my own
; work, and are copyright by that fact. I hereby place that set in
; the public domain. I place NO restriction of any kind on their
; use, adaptation, resale, possession or transfer.
;
; If you have a copy of this material, you have it with my blessings
; and good wishes. May it do well by you.
;
; I accept NO contingent responsibility of any kind for the use or
; any consequence of use of this software. If you use it, it is
; presumed that you know why and how to use it, and that you are in
; full control of all consequences of that use.
;
; David Hatch M.A.C.S.
;
; Due to ethics violations that could be levied against the modifier
; of this program, THE UNKNOWN HACKER can not take any credit for bringing
; this program to full functionality by making it a re-usable TSR.
; David Hatch's PUBLIC DOMAIN stipulation remains in full effect.
; Thanks.
; ******************************************************************
;
;------------------------------------------------
; macro- push all registers
;
pushall macro
push ax
push bx
push cx
push dx
push ds
push es
push si
push di
push bp
endm
;------------------------------------------------
; macro- pop all registers
;
popall macro
pop bp
pop di
pop si
pop es
pop ds
pop dx
pop cx
pop bx
pop ax
endm
CR EQU 0DH ;ASCII Carriage Return
LF EQU 0AH ;ASCII Line Feed
BELL EQU 07H ;ASCII Bell
TRUE EQU 0FFFFh
FALSE EQU NOT TRUE
ON EQU TRUE
OFF EQU FALSE
TAB EQU 09h
VECTORS SEGMENT AT 0000H ;Segment for vectors
ORG 08H * 4 ;Timer interrupt
TIMERV LABEL DWORD ;vector assignment
VECTORS ENDS
ROMDATA SEGMENT AT 0040H ;ROM BIOS Data area
ORG 1AH ;Keyboard buffer data
;
; ****** KEYBOARD BUFFER OPERATING ALGORITHM ******
;
;In IBM's notation as used for the PC keyboard buffer,
;a producer process will put in at the buffer TAIL, and
;a consumer process will take out at the buffer HEAD.
;
;If the buffer is empty, HEAD = TAIL. If the buffer is
;full, HEAD = WRAP(TAIL+2). The WRAP function applies to
;HEAD and TAIL, and operates to make the first location
;in the buffer logically follow the last location, so that
;the buffer is "wrapped" conceptually into a circle. The
;TAIL pointer is left pointing past the last character + scan
;entered, The HEAD pointer is left pointing at last taken.
;
KBHEAD DW ? ;Buffer HEAD pointer
KBTAIL DW ? ;Buffer TAIL pointer
ORG 80h
KBBUF DW ? ;Buffer data area
ORG 82h
KBBEND DW ? ;Buffer end(wrap) mark.
ROMDATA ENDS
CSEG SEGMENT PARA 'CODE'
ASSUME CS:CSEG, DS:CSEG, SS:CSEG, ES:NOTHING
ORG 100H ;Locate as .COM file
WHEN PROC FAR
JMP INIT ;Initialize resident & terminate.
; ************************************************************
; THIS IS SELF MODIFYING CODE - TAKE CARE IF EDITING
; ************************************************************
;
; This ISR begins with a switch jump. This is a relative jump,
; with a dynamically reset offset. It is well suited to ISR use,
; as it does not change the CPU state, or require save/restore
; operations. It is fast, causing little overhead.
;
; If this code is to be modified, check VERY carefully, and try
; to fully understand, all references to TIMEI+1. (The switch.)
TIMEI PROC NEAR ;This code is changed while running.
JMP SHORT TIME1 ;Switch jump waiting/active/inactive
; Operation of the ISR is over for this call. (It may be reused
; in a later invocation.) Exit, minimum delay, ISR is inactive.
; This is the last switch jump setting in a sequence of 3.
;
JMP DWORD PTR CS:TIVOFF ;Go to the previous ISR if inactive.
; Wait for the specified time, then switch this ISR
; from waiting to active character feeding. This is
; the first switch jump setting in a sequence of 3.
;
WAIT1:
PUSHF
PUSH AX ;Save registers
PUSH CX
PUSH DX
MOV AH,0 ;Function 0 of Interrupt 1AH
INT 1AH ;Read time of day in ticks.
CMP CX,CS:WHENHI ;If in the requested hour,
JNE WAIT2 ;Then:
MOV AX,CS:WHENLO ;Consider low word of time,
CMP AX,DX ;If time has arrived,
JNE WAIT2 ;Then:
MOV AL,CS:TIMESW ;Using the assembled switch value,
MOV CS:BYTE PTR TIMEI+1,AL ;start the keyboard buffer load.
WAIT2:
POP DX ;Restore registers
POP CX
POP AX
POPF
JMP DWORD PTR CS:TIVOFF ;Now go to the previous ISR.
; Time is up, feed characters into keyboard buffer,
; when done, switch ISR to inactive, doing nothing.
; This is the second switch jump setting in this
; sequence of 3. This switch jump setting uses the
; offset value as assembled in the source file.
TIME1:
PUSH AX ;Save registers
PUSH BX ;used in this code.
PUSH SI
PUSH DI
PUSH DS ;Save Data Segment
ASSUME DS:ROMDATA
MOV AX,ROMDATA ;Use ROM BIOS data segment
MOV DS,AX ;to see keyboard buffer.
MOV SI,CS:WHCMP ;Point to (CS:) command string
MOV BX,OFFSET SCANC ;Point to (CS:) scan code table
TIME2:
MOV DI,KBTAIL ;Use TAIL to put in keys.
INC DI ;Move DX on to the
INC DI ;next buffer position.
CMP DI,KBBEND ;Consider buffer end, if wrap,
JL TIME3 ;Then:
MOV DI,KBBUF ;wrap to start of buffer.
TIME3:
CMP DI,KBHEAD ;If the buffer is not full,
JE TIMEX ;Then:
MOV AL,CS:[SI] ;Read a character from the
INC SI ;command & step over it.
OR AL,AL ;If this character is the
JNE TIME4 ;end marker, Then:
MOV AL,CR ;provide automatic CR.
TIME4:
MOV AH,AL ;Save a copy of character
XLAT CS:SCANC ;look up scan code [BX]
XCHG AH,AL ;Scan code AH, ASCII in AL.
XCHG DI,KBTAIL ;Update TAIL, use original,
CMP AL,',' ;If not above the limit
JA TIME6 ;And:
CMP AL,'#'
JB TIME6 ;Then:
MOV AL,0
TIME6: MOV [DI],AX ;put keystroke in buffer.
CMP AL,CR ;If this was not the end,
JNE TIME2 ;continue, Else:
MOV CS:BYTE PTR TIMEI+1,0 ;Set switch jump to inactive.
TIMEX:
POP DS ;Restore Data Segment
POP DI ;Restore registers
POP SI
POP BX
POP AX
JMP DWORD PTR CS:TIVOFF ;Now go to the previous ISR.
; Scan code lookup table. Index into this table with an ASCII
; code, and receive back the scan code which would have been
; generated by an IBM compatible keyboard for that ASCII value.
; Position in table is ASCII code, content is scan code (decimal).
SCANC LABEL BYTE
; NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI
DB 00, 30, 48, 46, 32, 18, 33, 34, 14, 15, 28, 37, 38, 28, 49, 24
;
; DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US
DB 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 26, 43, 27, 07, 12
;
; F1 F2 F3 F4 F5 F6 F7 F8 F9 F10
; SPC ! " # $ % & ' ( ) * + , - . /
DB 57, 02, 40, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 12, 52, 53
;
; 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
DB 11, 02, 03, 04, 05, 06, 07, 08, 09, 10, 39, 39, 51, 13, 52, 53
;
; @ A B C D E F G H I J K L M N O
DB 03, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50, 49, 24
;
; P Q R S T U V W X Y Z [ \ ] ^ _
DB 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 26, 43, 27, 07, 12
;
; ` a b c d e f g h i j k l m n o
DB 41, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50, 49, 24
;
; p q r s t u v w x y z { | } ~ DEL
DB 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 26, 43, 27, 41, 00
; This variable holds the original assembled value of a relative
; jump offset, in the first instruction of this ISR. The actual
; running value is used as a dynamic switch, altering the function
; of the ISR with time. The value held here is the value used
; to select "Time is expired, load requested command" behavior.
;
TIMESW DB 00 ;Time expired switch value
TIMESWO DB 00 ;Time expired switch value ORG
TIVOFF DW 0000 ;Previous ISR ;offset
TIVSEG DW 0000 ;routine addr ;segment
WHENLO DW 0000 ;Time count comparison (Low)
WHENHI DW 0000 ;Time count comparison (High)
ISKIPO DW OFFSET ISKIP
WHCMP DW OFFSET WHCMD ;Delayed command pointer
WHCMD DB 80 DUP(00) ;Delayed command buffer
ISKIP DB BELL
DB "Memory Warning : Possible modification. Stay tuned!",CR,LF,BELL,'$'
ID DB 'WHEN v3.3 April 4, 1993',CR,LF,'$'
HH10 DB '0' ;Tens of hours (input time)
HH01 DB '0' ;Units of hours (input time)
DB ':'
MM10 DB '0' ;Tens of minutes (input time)
MM01 DB '0' ;Units of minutes (input time)
DB ':'
SS10 DB '0' ;Tens of seconds (input time)
SS01 DB '0' ;Units of seconds (input time)
DB " "
DB '$'
INTER DB ' ' ;Interactive mode (normally on)
REAL21 LABEL DWORD
REAL21_OFS DW ?
REAL21_SEG DW ?
INT21: PUSHF ; Save flags
CMP AH,0AAH ; Is this 'our' function?
JE OUR_FUNCTION
OLD: POPF ; Restore flags we called with
JMP CS:REAL21 ; Otherwise don't mess with the
; interrupt
; Check if caller is looking for this program
OUR_FUNCTION:
PUSH ES ; Save registers
PUSH CX ;
push ax
PUSH SI ;
PUSH DI ;
PUSH CS ; Set destination to us
POP ES ;
MOV DI,OFFSET ID ; Point to our ID
MOV CX,8 ;
CLD
REPE CMPSB ; See if ID is us
POP DI ; Restore registers
POP SI ;
MOV INTER,AL
pop ax
JCXZ ID_OK ; If zero, ID matches
POP CX ; Reset registers
POP ES ;
JMP OLD ; And continue to DOS
ID_OK:
pushall
MOV AL,INTER
CMP AL,'/'
JE ID_OK1
MOV DX,OFFSET ID
MOV AH,9
INT 21H
MOV DX,OFFSET ISKIP
MOV AH,9
INT 21H
ID_OK1: popall
POP CX ; Reset CX
ADD SP,2 ; ES stays the same
NOT BX ; Invert BX to say we're here
POPF
IRET
NOP
TIMEI ENDP
;*********************************************************************
;* *
;* Release memory from this point on for reuse by DOS. *
;* *
;*********************************************************************
;
TSREND: ;Release from here
ENTES DW 0000 ;ES pointing to program's PSP
CCOUNT DB 00 ;Command line character count
RESIDENT DB 0FFH
FIRSTCH DB 002H
TORG DB 0FFH
; Initialize T.S.R. resident portion, presetting as required. This
; code is no longer present after T.S.R. is running, as this RAM
; area has been returned to DOS for other uses.
INIT:
; Parse the command line, exit if no request present.
; Parse time, then command request with full filespec.
MOV SI,0081H ;Point to command line
MOV AL,[SI-1] ;Use character count of this
MOV CCOUNT,AL ;command line, as entered.
; Consume spaces, until first non-space character
INIT1:
CALL GETCH ;If there is a character
JC INITL ;available, And:
CMP AL,' ' ;It is not an ASCII Space,
JE INIT1 ;Then:
CMP AL,'/' ;If interactive mode is OFF
JNE INITL ;Then:
MOV INTER,AL ;Suppress user interaction
JMP SHORT INIT1 ;and continue to scan.
INITL: MOV AH,0AAH
MOV AL,INTER
MOV SI,OFFSET ID
XOR BX,BX
INT 21H
PUSH ES
MOV ENTES,ES ;Save register for exit
INC BX
JZ PARSEA
; pointing to this program's ISR resident code.
MOV AX,3508H ;Read existing interrupt
INT 21H ;08h vector contents
MOV TIVOFF,BX ;and use them as destination
MOV TIVSEG,ES ;pointer to previous ISR code.
MOV AX,CS ;The Timer interrupt segment
MOV DS,AX ;must point to this code segment,
MOV DX,OFFSET TIMEI ;referring to ISR entry point.
MOV AX,2508H ;Access interrupt 08h, routing
INT 21H ;via this program's handler.
MOV AX,3521H ;Read existing interrupt
INT 21H ;08h vector contents
MOV REAL21_OFS,BX ;and use them as destination
MOV REAL21_SEG,ES ;pointer to previous ISR code.
MOV AX,CS ;The Timer interrupt segment
MOV DS,AX ;must point to this code segment,
MOV DX,OFFSET INT21 ;referring to ISR entry point.
MOV AX,2521H ;Access interrupt 21h, routing
INT 21H ;via this program's handler.
MOV RESIDENT,0
MOV AL,BYTE PTR TIMEI+1 ;Read assembled branch offset
MOV TIMESWO,AL ;switch value & save it, then
PARSEA: POP ES
MOV ENTES,ES ;Save register for exit
CMP RESIDENT,0
JE FIRSTT
MOV AL,ES:BYTE PTR TIMEI+1 ;Save time monitor entry STATUS
MOV TORG,AL
FIRSTT: MOV AL,ES:TIMESWO ;Read assembled branch offset org
MOV ES:TIMESW,AL ;switch value & save it, then
MOV ES:BYTE PTR TIMEI+1,0 ;Kill time monitor but wait and see.
; Parse the command line, exit if no request present.
; Parse time, then command request with full filespec.
PARSEB: MOV SI,0081H ;Point to command line
MOV AL,[SI-1] ;Use character count of this
MOV CCOUNT,AL ;command line, as entered.
; Consume spaces, until first non-space character
PARSE1:
MOV FIRSTCH,1
CALL GETCH ;If there is a character
JC BADT1 ;available, And:
CMP AL,' ' ;It is not an ASCII Space,
JE PARSE1 ;Then:
CMP AL,'/' ;If interactive mode is OFF
JNE PARSE2 ;Then:
MOV FIRSTCH,0
MOV INTER,AL ;Suppress user interaction
JMP SHORT PARSE1 ;and continue to scan.
; Accept HH [ :MM [ :SS ]] time specification input
PARSE2:
PUSHALL
MOV AL,INTER
CMP AL,' '
JNE PARSE3
MOV AL,RESIDENT
CMP AL,0
JNE PARSE3
MOV DX,OFFSET ID ;Format the screen, and
MOV AH,9 ;Display the details.
INT 21H
PARSE3:
POPALL
MOV FIRSTCH,0
MOV AH,'2' ;Tens of hours .LE. 2
CALL CHNUM ;If valid digit,
JC BADT1 ;Then:
MOV ES:HH10,AL ;Accept Tens of hours.
CALL GETCH ;If there is a character
JC BADTM ;available, Then:
MOV AH,'9' ;Units of hours .LE. 9
CALL CHNUM ;If valid digit,
JC BADT1 ;Then:
MOV ES:HH01,AL ;Accept Units of hours.
CALL GETCH ;If there is a character
JC BADT1 ;available, Then:
CMP AL,' ' ;If not the terminator,
JZ TIMOK ;And:
CMP AL,':' ;It is a valid time
JNZ BADTM ;separator, Then:
CALL GETCH ;If there is a character
BADT1: JC BADTM ;available, Then:
MOV AH,'5' ;Tens of minutes .LE. 5
CALL CHNUM ;If valid digit,
JC BADTM ;Then:
MOV ES:MM10,AL ;Accept Tens of minutes.
CALL GETCH ;If there is a character
JC BADTM ;available, Then:
MOV AH,'9' ;Units of minutes .LE. 9
CALL CHNUM ;If valid digit,
JC BADTM ;Then:
MOV ES:MM01,AL ;Accept Units of minutes.
CALL GETCH ;If there is a character
JC BADTM ;available, Then:
CMP AL,' ' ;If not the terminator,
JZ TIMOK ;And:
CMP AL,':' ;It is a valid time
JNZ BADTM ;separator, Then:
CALL GETCH ;If there is a character
JC BADTM ;available, Then:
MOV AH,'5' ;Tens of seconds .LE. 5
CALL CHNUM ;If valid digit,
JC BADTM ;Then:
MOV ES:SS10,AL ;Accept Tens of seconds.
CALL GETCH ;If there is a character
JC BADTM ;available, Then:
MOV AH,'9' ;Units of seconds .LE. 9
CALL CHNUM ;If valid digit,
JC BADTM ;Then:
MOV ES:SS01,AL ;Accept Units of seconds.
JMP SHORT TIMOK ;Time input is valid.
; Report error in time value input
BADTM:
CMP FIRSTCH,1
JE BADTM0
JMP BADTM2
BADTM0: CMP RESIDENT, 0FFH ;TRUE
JE BADTM1
MOV ES:BYTE PTR TIMEI+1,0 ;Kill time monitor if first time thru
MOV TORG,0
BADTM1: JMP EXIT
BADTM2: MOV AL,01H ;Assign error level (this error)
MOV DX,OFFSET TIMERR ;Select time input error message
JMP ERREX ;and exit with error display.
; Convert time into tick count value, which will
; be used for comparison during the delay period.
;
; IBM PC time is kept in 18.2 (approx) ticks per second,
; or more precisely 65536 (16 bit binary) per hour.
;
; Conversion in this program is handled by the following:
; High word=hours(exact), Low word=(mins * 1092.25(exact))
; plus (seconds * 18.25(approximation).
TIMOK:
MOV BX,OFFSET ES:HH10 ;Consider hours,
CALL ASCBIN ;convert to binary,
MOV ES:WHENHI,AX ;set tick count(high).
MOV BX,OFFSET ES:MM10 ;Consider minutes,
CALL ASCBIN ;convert to binary,
MOV BX,AX ;copy the result.
SHR AX,1 ; /2 Multiply hours
SHR AX,1 ; /4 (0.25) by 1092.25 to
SHL BX,1 ; * 2 get ticks per
SHL BX,1 ; * 4 hour.
ADD AX,BX ; ( Accumulation = * 4.25 )
SHL BX,1 ; * 8
SHL BX,1 ; * 16
SHL BX,1 ; * 32
SHL BX,1 ; * 64
ADD AX,BX ; ( Accumulation = * 68.25 )
SHL BX,1 ; * 128
SHL BX,1 ; * 256
SHL BX,1 ; * 512
SHL BX,1 ; * 1024
ADD AX,BX ; ( Accumulation = * 1092.25 )
MOV DX,AX ; Save hours result.
MOV BX,OFFSET ES:SS10 ;Consider seconds,
CALL ASCBIN ;convert to binary,
MOV BX,AX ;copy the result.
SHR AX,1 ; /2 Multiply seconds
SHR AX,1 ; /4 (0.25) by 18.2 to get the
SHL BX,1 ; * 2 ticks per second.
ADD AX,BX ; ( Accumulation = * 2.25 )
SHL BX,1 ; * 4 An approximation of
SHL BX,1 ; * 8 18.25 is used, rather
SHL BX,1 ; * 16 than actual 18.2.
ADD AX,BX ; ( Accumulation = * 18.25 )
ADD AX,152 ;Add in correction factors
ADD AX,DX ;Add in hours result
MOV ES:WHENLO,AX ;completing tick value.
; Accept command tail, ready to enter after delay expires
MOV BX,OFFSET ES:WHCMD ;Point to WHEN command buffer
CMDCP:
CALL GETCH ;If there is a character
JC BADCM ;available, And:
CMP AL,' ' ;It is an ASCII Space,
JNE CMDC1 ;Then: Throw it out, and
JMP SHORT CMDCP ;scan another.
; Report error in command string input
BADCM:
MOV AL,02H ;Assign error level (this error)
MOV DX,OFFSET CMDERR ;Select time input error message
JMP ERREX ;and exit with error display.
CMDC1:
MOV ES:[BX],AL ;Put it into the command line
INC BX ;step over it,
CALL GETCH ;If there is another character
JNC CMDC1 ;available, continue, Else:
CMDCX:
CMP BX,ES:ISKIPO ; Clear the rest of the buffer
JE CMDCE
MOV AL,0
MOV ES:[BX],AL
INC BX
JMP CMDCX
CMDCE:
MOV ES:BYTE PTR TIMEI+1,5 ;Start time monitor & wait.
MOV TORG,5
; Report action if interactive, exit to DOS, no error.
; (ISR handler remains installed as a resident.)
EXIT:
MOV AX,0
EXIT_0:
PUSH AX
MOV AL,TORG
MOV ES:BYTE PTR TIMEI+1,AL ;Start time monitor from original value.
CALL RPSTAT
CMP RESIDENT, 0FFH ;TRUE
JE EXIT_1
; Set up interrupt vector for timer (vector 08H *4)
; release memory allocated to our environment segment
;
; MOV ES,CS:[2CH] ; environment memory segment
; MOV AH,049H ; give it back to system
; INT 021H ;
;
; calculate our resident size rounded-up to the next paragraph
;
MOV DX,OFFSET ENTES + 15 ; length of resident code
MOV CL,4 ; set (cl) to divide by
SHR DX,CL ; 16 to get para count
;
; terminate and leave our resident routines in place
;
POP AX
MOV AH,031H ; tsr op and return code
INT 021H ; terminate
; MOV ES,ENTES
; MOV DX,OFFSET TSREND
; INT 27H
EXIT_1: MOV AH,4CH
INT 21H
; Report error if interactive, exit to DOS with error level.
ERREX:
PUSH AX ;Save error level value.
MOV AL,INTER ;Consider interactive flag
CMP AL,' ' ;If interactive with a user,
JNE ERRE1 ;Then:
MOV AH,9 ;Display the selected error
INT 21H ;message for him.
ERRE1:
MOV AL,INTER
CMP AL,' '
JNE ERRE2
MOV DX,OFFSET ACTERR
MOV AH,9
INT 21H
ERRE2:
MOV ES,ENTES ;Restore entry PSP segment
POP AX ;Use the specified error level
MOV ES:BYTE PTR TIMEI+1,0 ;to inform DOS processes of
;the error in WHEN and
MOV TORG,0
JMP EXIT_0 ;KILL this thing.
;(Leave Resident Portion...)
TIMERR DB BELL
DB "Program Error : "
DB "Time specified is in the wrong format. We don't know WHEN!",'$'
CMDERR DB BELL
DB "Program Error : "
DB "Command must be specified. We know WHEN, but not what to do!",'$'
ACTERR DB CR,LF,BELL
DB " "
DB "All pending calls have been cancelled! Please try again!",CR,LF
DB "Command syntax : WHEN HH[:MM[:SS]] command [command tail]",CR,LF,'$'
; Decrement character count CCOUNT. If it goes to 0, return
; flag C = 1, and exit. If there are characters available,
; read a character from string pointed to by SI & step SI on.
;
GETCH PROC NEAR
DEC CCOUNT ;If there is a character
JS GETCE ;Then:
MOV AL,[SI] ;Read a character,
INC SI ;step over it,
CLC ;clear the carry flag
RET ;and return.
GETCE:
XOR AL,AL ;AL = 0, C = 0
CMC ;C = 1 (Report error)
RET
GETCH ENDP
; Check current contents of AL. Value must be .GE. '0'
; and .LE. than the upper limit specified in AH. No data
; is changed, but the result is returned in the C flag.
; C = 0, AL is valid number. C = 1, Error, AL is invalid.
;
CHNUM PROC NEAR
CMP AL,AH ;If not above the limit
JA CHNUE ;And:
CMP AL,'0' ;If ASCII 0 or greater,
JB CHNUE ;Then:
RET ;Return, C = 0
CHNUE:
STC ;Error has been seen,
RET ;Return, C = 1
CHNUM ENDP
; Convert 2 Asci digits (high order first) pointed to
; by register BX, into equivalent binary in AX.
;
ASCBIN PROC NEAR
MOV AL,ES:[BX] ;Read high digit,
INC BX ;step over it,
AND AX,000FH ;strip to binary, and
MOV CL,10D ;multiply it by 10.
MUL CL
MOV CL,ES:[BX] ;Read the low digit
AND CX,000FH ;strip to binary, and
ADD AX,CX ;add it in.
RET
ASCBIN ENDP
;report status of TSR
;
RPSTAT PROC NEAR
MOV AL,INTER ;Consider interactive flag
CMP AL,' ' ;If interactive with a user,
JNE RPST3 ;Then:
MOV DX,OFFSET WHRUN1 ;Format the screen, and
MOV AH,9 ;Display the details.
INT 21H
PUSH DS
MOV AX,ES
MOV DS,AX
MOV DX,OFFSET ES:HH10 ;Report the requested time,
MOV AH,9 ;expanding if required.
INT 21H
POP DS
MOV DX,OFFSET WHRUN2 ;Format the screen, and
MOV AH,9 ;Display the details.
INT 21H
MOV BX,OFFSET ES:WHCMD ;Report the command to be run
;at specified time, as entered.
RPST1:
MOV DL,ES:[BX] ;Take a character from the
INC BX ;command, and step over it.
OR DL,DL ;If not a terminating NULL,
JZ RPST2 ;Then:
MOV AH,2 ;Display this character
INT 21H
JMP SHORT RPST1 ;Continue with command string.
RPST2:
CMP TORG,0
JNE TRPST1
MOV DX,OFFSET INACTV
JMP TRPST
TRPST1: CMP TORG,5
JNE TRPST2
MOV DX,OFFSET ACTIVE
JMP TRPST
TRPST2: MOV DX,OFFSET WHOKNW
TRPST: MOV AH,9
INT 21H
RPST3: RET
WHRUN1 DB 'At This Time : $'
WHRUN2 DB CR,LF,'Do This Command: $'
ACTIVE DB CR,LF,'Current Status : *active*',CR,LF,CR,LF,'$'
INACTV DB CR,LF,'Current Status : *inactive*',CR,LF,CR,LF,'$'
WHOKNW DB CR,LF,'Current Status : *status unknown*',CR,LF,CR,LF,'$'
RPSTAT ENDP
WHEN ENDP
CSEG ENDS
END WHEN